Implementing a Digital Reverberator

Reverberation

Real life reverberation refers to a high density of echoes occuring due to phase differences in waves due to reflection and absorbtion off of materials. An example of reverberation would be clapping in an empty theatre, and the reflections of the clap would be what we call "reverb" on the clap. Reverb is distinct from an echo, reverb refers to closely spaced reflections in time, like a pulse train.

Often in audio engineering reverberation is a desired effect which producers want to add to a vocal layer or an instrument to create a "spacey" sound. Digitally, a simple echo is usually implemented with either an all pass filter, or a comb filter.

A simple feedforward comb filter is implemented as follows:

combfilter.png

Assuming the phase delay is $T$, then the difference equation for this filter is

$$y[n] = x[n] + \alpha x[n-T] $$

where $\alpha$ is a linear gain applied to the delayed signal. By setting $\alpha =1$ we can see that we have implemented an echo on any input $x[n]$. But we want to simulate the effect of many reflections (as in the case of clapping in the empty lecture theatre), and this only describes one echo. Before proceeding with reverberation design, let's take a look at the transfer function which describes this system. By taking the $Z$ transform of the difference equation we obtain

$$Y(z) = X(z) + \alpha z^{-T} X(z) \Longrightarrow H(z) = \frac{Y(z)}{X(z)} = 1 + \alpha z^{-T} = \frac{\alpha + z^T}{z^T} $$

Again for the purposes of generating a pure echo, we set $\alpha =1$ and to investigate the frequency response we restrict $z=e^{j\omega}$:

$$H(e^{j\omega}) = \frac{1+e^{j\omega T}}{e^{j\omega T}} $$

We wish to look at the magnitude and phase response of such a filter. Let's assume that the delay is one unit: $T=1$. The following libraries will be used throughout this notebook:

With these libraries lets begin by looking at the magnitude and phase response of the comb filter in Python for different delay times, $T$.

We can see that this filter has periodic "nulls", meaning at certain frequencies, periodically spaced, the filter attenuates them deeply. The magnitude response is what gives this filter the name "comb filter". Conceptually we can imagine that at the nulls, waves of that frequency will deconstructively interfere and otherwise we have constructive interference. Or we could imagine this response describes a room made of many composite materials, and frequencies at the nulls would get absorbed by the room.

Before applying the filter we need to consider how to pick a value of $T$. This value of $T$ is measured in samples, which means that to get a noticable delay we need to pick $T$ on the order of milliseconds or greater. Typically audio is sampled at a rate of $f_s = 44100\,\text{samples}/\text{s}$. This means that the time duration of one sample is

$$\tau_\text{sample} = \frac{1}{f_s} $$

and if we have $N$ samples the total time of the signal is

$$\tau_\text{signal} = \frac{N}{f_s}$$

In order to pick a sensible $T$, the value of $\tau_\text{sample}$ should be calculated and then multiplied to give a substantial delay.

We can see from the audio output that an echo was generated (if the value of $T$ is increased large enough the echoes per second increases). One echo however is not reverberation. Reverberation would consist of many signals arriving at your ear at slightly different times. We can digitally simulate reverberation by using many combing filters. Each combing filter representing a slight deviation in phase for the incoming signal. Ideally we'd want hundreds of echoes per second to simulate genuine reverberation. To do this we would need to have each filter combined in a parallel combination so the signals can be processed simultaneously to produce many echoes of different phases which are closely spaced out in time. This method was first done by Manfred Schroeder in 1962 at Bell Labs and his original paper was a large part of the inspiration for this notebook and some insights into the design I surely never would have arrived at my own (using a series all-pass cascade was something I never considered for example.)

How can we construct parallel comb filters?

parallelcomb.png

From the parallel connection above we see the following difference equation describes the filter:

$$y[n] = a_0x[n] + a_1x[n-T_1] + a_2x[n-T_2] + a_3x[n-T_3] + a_4x[n-T_4] $$

TODO: Parallel programming? Probably overkill but it would be fun to try

We can hear more echoes with four combing filters implemented, however this still isn't a reverb effect. This is because even four combing filters together will not produce enough echoes to produce a reverberation effect. However, all is not lost. This is the only first half of a working simple reverberator. The other half consists of two all pass filters in series. You may ask: What is the point of an all pass filter? Why would we want to pass something through a filter which will not edit any frequency content at all? The answer is straightforward to understand: The comb filters each create a certain amount of echoes per second at different delays, then by passing these echoes through an all-pass filter with an additional delay will cause echoes on the echoes, and then passing these into another all-pass filter will cause echoes on the echoes which echoed off the echoes. A cascading effect of echo production will cause the density of echoes to increase to produce a digital reverberator.

The final result here is quite a metallic reverb, it sounds much more like someone speaking through a tube or tunnel than a nice reverb that one would usually want to put onto an audio layer. The audio still has some artifacts that need to be corrected as well.

This reverb design was the first digital reverb design ever, and there can be modifications made to it to improve performance. But for now this is where I stop as generally this type of reverberator is quite metallic. I believe in the paper cited above, and in other literature on this specific digital reverberator there are optimal formulas for phase shifts and gains.

TODO: There is artifacts in the audio from the reverb filter. This is most likely due to the delay values in the comb filter feed back lines. It's possible that the same audio chunk is being reflected at nearly the same time causing a popcorn sound effect in the audio.